package com.imooc.alllearning.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.imooc.alllearning.common.PageQuery;
import com.imooc.alllearning.common.PageResult;
import com.imooc.alllearning.domain.dto.UserDTO;
import com.imooc.alllearning.domain.dto.UserExportDTO;
import com.imooc.alllearning.domain.dto.UserQueryDTO;
import com.imooc.alllearning.service.ExcelExportService;
import com.imooc.alllearning.service.FileService;
import com.imooc.alllearning.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * Excel到处服务实现类
 * @Author: crowsjian
 * @Date: 2020/4/1 22:49
 */
@Slf4j
@Service
public class ExcelExportServiceImpl implements ExcelExportService {
    @Resource(name="localFileServiceImpl")
    private FileService fileService;

    @Autowired
    private UserService userService;

    /**
     * 执行数据库查询和excel导出，将数据写入到outputStream中
     * @param outputStream
     * @param query
     */
    public void  export(OutputStream outputStream, UserQueryDTO query){
        // 1 创建一个EasyExcel导出对象
        ExcelWriter excelWriter = EasyExcelFactory.write(outputStream, UserExportDTO.class).build();
        // 2 分批加载数据
        PageQuery<UserQueryDTO> pageQuery = new PageQuery<>();
        pageQuery.setQuery(query);
        pageQuery.setPageSize(2);
        int pageNo = 0;

        PageResult<List<UserDTO>> pageResult;
        do{
            pageQuery.setPageNo(++pageNo);
            // 数据库查询
            pageResult = userService.query(pageQuery);
            //数据转换： UserDTO 转换成 UserExportDTO
            List<UserExportDTO> userExportDTOList = Optional.ofNullable(pageResult.getData())
                    .map(List::stream)
                    .orElseGet(Stream::empty)
                    .map(userDTO -> {
                        UserExportDTO userExportDTO = new UserExportDTO();
                        BeanUtils.copyProperties(userDTO, userExportDTO);
                        return userExportDTO;
                    }).collect(Collectors.toList());
            // 3 导出分批加载的数据
            //将数据写入到不同的sheet页中
            WriteSheet writeSheet = EasyExcelFactory.writerSheet(pageNo, "第"+pageNo+"页").build();
            //总页数大于当前页 说明还有数据 需要再次执行
            excelWriter.write(userExportDTOList, writeSheet);
            log.info("成功导出[{}]页！", pageNo);
        }while(pageResult.getPageNum()>pageNo);
        // 4 收尾 执行finish，才会关闭Excel文件流
        excelWriter.finish();
        log.info("导出成功！");
    }

    @Override
    public void export(UserQueryDTO query, String filename) {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

        //实现数据导出到excel中
        export(outputStream, query);

        //输出流转输入流
        ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
        //实现文件上传
        fileService.upload(inputStream, filename);
    }

    /**
     * @Async标注 使用线程池执行方法
     * @param query
     * @param filename
     */
    @Async("exportServiceExecutor")
    @Override
    public void asyncExport(UserQueryDTO query, String filename) {
        export(query, filename);
    }
}
